#pragma once

#include <functional>
#include <sys/socket.h>

class UdpSocketBase;

/*
 * @brief 	一个UDP Socket的包装类库的对外文件
 * @note 	这是一个简化的版本，有意忽略一些事件，只保留Receive data和Close
 *socket两个事件。 demo详见测试用例。
 * @note 本类库使用libuv库和C++11以上标准
 *
 */
class UdpSocketWrapper {
  public:
    using CALL_BACK = std::function<void(
        const uint8_t *, size_t, const struct sockaddr *, UdpSocketWrapper *)>;
    using ON_CLOSE = std::function<void(const UdpSocketWrapper *)>;
    using ON_SEND_FAILED = std::function<void(int, const UdpSocketWrapper *)>;

  public:
    /*
     * @brief 获取返回值的描述字符串
     * @note  该函数主要应用于Listen接口
     */
    static const char *GetErrorScript(int error);

  public:
    UdpSocketWrapper();
    virtual ~UdpSocketWrapper();

  public:
    int Listen(const char *ip, uint16_t port, const CALL_BACK &onReceive);
    int Listen(const char *ip, uint16_t port);
    void Destroy();

  public:
    void Send(const uint8_t *data, size_t len, const struct sockaddr *addr);
    void Send(const uint8_t *data, size_t len, const char *ip, uint16_t port);

  public:
    const struct sockaddr *GetLocalAddress() const;
    std::string GetLocalIP();
    uint16_t GetLocalPort() const;
    size_t GetRecvBytes() const;
    size_t GetSentBytes() const;

  private:
    int Listen(const char *ip, uint16_t port, const CALL_BACK &onReceive,
               const ON_CLOSE &onClose, const ON_SEND_FAILED &onSendFailed);

  private:
    UdpSocketBase *impl{nullptr};
};